package cn.itcast.nems.order.service.impl;

import cn.hutool.core.lang.Assert;
import cn.itcast.ic.common.exception.v2.BizExceptionProducer;
import cn.itcast.nems.common.account.AccountHolder;
import cn.itcast.nems.common.enumeration.BizNumberTypeEnum;
import cn.itcast.nems.common.service.BizNumberService;
import cn.itcast.nems.order.dao.dataobject.OrderPaymentFlowDO;
import cn.itcast.nems.order.dao.entity.OrderEvent;
import cn.itcast.nems.order.dao.entity.OrderPaymentFlow;
import cn.itcast.nems.order.dao.mapper.OrderPaymentFlowMapper;
import cn.itcast.nems.order.dto.OrderEventTypeEnum;
import cn.itcast.nems.order.dto.OrderPaymentFlowChargeDTO;
import cn.itcast.nems.order.enumeration.OrderErrorBodyEnum;
import cn.itcast.nems.order.service.OrderEventService;
import cn.itcast.nems.order.service.OrderPaymentFlowService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * <p>
 * 销售订单-支付流水。注：只记录实际发生，正反向流水都保存在该表。 服务实现类
 * </p>
 *
 * @author liyong
 * @since 2023-08-31
 */
@Service
@AllArgsConstructor
public class OrderPaymentFlowServiceImpl extends ServiceImpl<OrderPaymentFlowMapper, OrderPaymentFlow> implements OrderPaymentFlowService {

    private final OrderPaymentFlowMapper orderPaymentFlowMapper;
    private final OrderEventService orderEventService;
    private final BizNumberService bizNumberService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeCharge(String orderId, List<OrderPaymentFlowChargeDTO> flowCharges) {
        Assert.notBlank(orderId, BizExceptionProducer.produce(OrderErrorBodyEnum.ORDER_ID_NOT_FOUND));
        Assert.notEmpty(flowCharges, BizExceptionProducer.produce(OrderErrorBodyEnum.ORDER_JOURNAL_NOT_FOUND));
        
        OrderPaymentFlow flow = null;
        for (OrderPaymentFlowChargeDTO charge : flowCharges) {
            flow = orderPaymentFlowMapper.selectOne(new LambdaQueryWrapper<OrderPaymentFlow>()
                                    .eq(OrderPaymentFlow::getOrderId, orderId)
                                    .eq(OrderPaymentFlow::getJournalType, charge.getJournalType())
                                    .eq(OrderPaymentFlow::getJournalNo, charge.getJournalNo())
                                    .eq(OrderPaymentFlow::getDeletedFlag, Boolean.FALSE), false);
            
            Assert.notNull(flow, BizExceptionProducer.produce(OrderErrorBodyEnum.ORDER_JOURNAL_DATA_NOT_FOUND , charge.getJournalType(), charge.getJournalType()));
            orderPaymentFlowMapper.update(null, new LambdaUpdateWrapper<OrderPaymentFlow>()
                    .set(OrderPaymentFlow::getCharge, charge.getCharge())
                    .set(OrderPaymentFlow::getChargeRate, charge.getRate())
                    .eq(OrderPaymentFlow::getOrderId, orderId)
                    .eq(OrderPaymentFlow::getJournalType, charge.getJournalType())
                    .eq(OrderPaymentFlow::getJournalNo, charge.getJournalNo())
                    .eq(OrderPaymentFlow::getDeletedFlag, Boolean.FALSE)
                    );
        }
        
        orderEventService.save(new OrderEvent(orderId, OrderEventTypeEnum.CHANGED_PAYMENT_CHARGE.getName(), "修改支付手续费"));
    }

    @Override
    public OrderPaymentFlow addOrderPaymentFlow(OrderPaymentFlowDO orderPaymentFlow) {
        OrderPaymentFlow flow = new OrderPaymentFlow();
        BeanUtils.copyProperties(orderPaymentFlow, flow);
        String no  = this.bizNumberService.next(BizNumberTypeEnum.ORDER_PAYMENT_FLOW);
        flow.setAmount(Integer.parseInt(orderPaymentFlow.getAmount()));
        flow.setNo(no);
        this.orderPaymentFlowMapper.insert(flow);
        return flow;
    }

    @Override
    public IPage<OrderPaymentFlowDO> findPageList(Page<OrderPaymentFlowDO> page, OrderPaymentFlowDO orderPaymentFlowDO) {
        if (!AccountHolder.hasEmployeeGroups()) {
            return page;
        }
        orderPaymentFlowDO.setEmployeeGroups(AccountHolder.getEmployeeGroups());
        return orderPaymentFlowMapper.findPageList(page, orderPaymentFlowDO);
    }

}
